package com.redepronik.negosys.invfac.service;

import static com.redepronik.negosys.utils.Utils.presentaMensaje;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.faces.application.FacesMessage;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.redepronik.negosys.invfac.dao.BodegaDao;
import com.redepronik.negosys.invfac.entity.Bodega;
import com.redepronik.negosys.invfac.entity.Bodegaempleadocargo;
import com.redepronik.negosys.rrhh.entity.Empleadocargo;
import com.redepronik.negosys.rrhh.service.EmpleadoService;

@Service
public class BodegaServiceImpl implements BodegaService {

	@Autowired
	private BodegaDao bodegaDao;

	@Autowired
	private EmpleadoService empleadoService;

	private ValidatorFactory factory = Validation
			.buildDefaultValidatorFactory();
	private Validator validator = factory.getValidator();

	public void actualizar(Bodega bodega) {
		Set<ConstraintViolation<Bodega>> violations = validator
				.validate(bodega);
		if (violations.size() > 0)
			for (ConstraintViolation<Bodega> cv : violations)
				presentaMensaje(FacesMessage.SEVERITY_INFO, cv.getMessage());
		else if (bodegaDao.comprobarIndices(Bodega.class, "nombre",
				bodega.getNombre(), String.valueOf(bodega.getBodegaid()))) {
			presentaMensaje(FacesMessage.SEVERITY_ERROR,
					"LA BODEGA: " + bodega.getNombre() + " YA EXISTE", "error",
					false);
		} else {
			bodegaDao.actualizar(bodega);
			presentaMensaje(FacesMessage.SEVERITY_INFO, "MODIFICO LA BODEGA: "
					+ bodega.getNombre(), "error", true);
		}
	}

	public void eliminar(Bodega bodega) {
		bodega.setActivo(bodega.getActivo() ? false : true);
		bodegaDao.actualizar(bodega);
		presentaMensaje(FacesMessage.SEVERITY_INFO,
				bodega.getActivo() ? "ACTIVO LA BODEGA: " + bodega.getNombre()
						: "DESACTIVO LA BODEGA: " + bodega.getNombre());
	}

	public List<Bodega> insertar(Bodega bodega) {
		bodega.setActivo(true);
		Set<ConstraintViolation<Bodega>> violations = validator
				.validate(bodega);
		if (violations.size() > 0)
			for (ConstraintViolation<Bodega> cv : violations)
				presentaMensaje(FacesMessage.SEVERITY_INFO, cv.getMessage());
		else if (bodegaDao.comprobarIndices(Bodega.class, "nombre",
				bodega.getNombre(), String.valueOf(bodega.getBodegaid()))) {
			presentaMensaje(FacesMessage.SEVERITY_ERROR,
					"LA BODEGA: " + bodega.getNombre() + " YA EXISTE", "error",
					false);
		} else {
			bodegaDao.insertar(bodega);
			presentaMensaje(FacesMessage.SEVERITY_INFO, "INSERTO LA BODEGA: "
					+ bodega.getNombre(), "error", true);
		}
		return obtenerTodos();
	}

	public void insertarBodeguero(Bodega bodega,
			List<Bodegaempleadocargo> listaBodegaEmpleadoCargo,
			Empleadocargo bodeguero) {
		boolean bd = false;
		if (bodeguero.getEmpleadocargoid() == 0
				|| bodeguero.getEmpleadocargoid() == null)
			presentaMensaje(FacesMessage.SEVERITY_ERROR, "ESCOJA UN BODEGUERO");
		else {
			for (Bodegaempleadocargo bec : listaBodegaEmpleadoCargo)
				if (bec.getEmpleadocargo().getEmpleadocargoid() == bodeguero
						.getEmpleadocargoid()) {
					bd = true;
					break;
				}
			if (bd)
				presentaMensaje(FacesMessage.SEVERITY_ERROR,
						"YA EXISTE ESTE BODEGUERO");
			else {
				Bodegaempleadocargo bec = new Bodegaempleadocargo();
				bec.setBodega(bodega);
				bec.setEmpleadocargo(empleadoService
						.obtenerPorEmpleadoCargoId(bodeguero
								.getEmpleadocargoid()));
				bec.setActivo(true);
				listaBodegaEmpleadoCargo.add(bec);
				presentaMensaje(FacesMessage.SEVERITY_INFO,
						"BODEGUERO ASOCIADO CORRECTAMENTE");
			}
			bodeguero = new Empleadocargo();
		}
	}

	public void eliminarBodeguero(Bodega bodega, Bodegaempleadocargo encargado) {
		int index = bodega.getBodegaempleadocargos().indexOf(encargado);
		bodega.getBodegaempleadocargos()
				.get(index)
				.setActivo(
						bodega.getBodegaempleadocargos().get(index).getActivo() ? false
								: true);
		presentaMensaje(FacesMessage.SEVERITY_INFO, (bodega
				.getBodegaempleadocargos().get(index).getActivo() ? "ACTIVO "
				: "DESACTIVO ")
				+ "EL BODEGUERO: "
				+ bodega.getBodegaempleadocargos().get(index)
						.getEmpleadocargo().getEmpleado().getPersona()
						.getApellido()
				+ " "
				+ bodega.getBodegaempleadocargos().get(index)
						.getEmpleadocargo().getEmpleado().getPersona()
						.getNombre());
	}

	public void guardarBodegueros(
			List<Bodegaempleadocargo> listaBodegaEmpleadoCargo, Bodega bodega) {
		if (listaBodegaEmpleadoCargo.isEmpty()) {
			presentaMensaje(FacesMessage.SEVERITY_ERROR,
					"INGRESE POR LO MENOS UN BODEGUERO", "error", true);
		} else {
			if (bodega.getBodegaempleadocargos() == null)
				bodega.setBodegaempleadocargos(new ArrayList<Bodegaempleadocargo>());

			bodega.setBodegaempleadocargos(listaBodegaEmpleadoCargo);
			actualizar(bodega);
			presentaMensaje(FacesMessage.SEVERITY_INFO,
					"SE ACTUALIZÓ CON EXITO", "error", false);
		}
	}

	public List<Bodega> obtenerActivos() {
		List<Bodega> list = bodegaDao.obtenerPorHql(
				"select b from Bodega b where b.activo=true order by b.nombre",
				new Object[] {});
		return list;
	}

	public Bodega obtenerPorBodegaId(int bodegaId) {
		Bodega bodega = bodegaDao.obtenerPorId(Bodega.class, bodegaId);
		return bodega;
	}

	public List<Bodega> obtenerPorBodeguero(String bodeguero) {
		List<Bodega> list = bodegaDao
				.obtenerPorHql(
						"select distinct b from Bodega b "
								+ "inner join b.bodegaempleadocargos bec "
								+ "inner join bec.empleadocargo ec "
								+ "inner join ec.cargo c "
								+ "inner join ec.empleado e "
								+ "inner join e.persona p "
								+ "where b.activo=true and bec.activo=true and ec.actual=true and c.activo=true and e.activo=true and p.activo=true and c.cargoid=3 and p.cedula=?1",
						new Object[] { bodeguero });

		return list;
	}

	public List<Bodega> obtenerPorEan(String ean) {
		List<Bodega> list = bodegaDao
				.obtenerPorHql(
						"select distinct b from Bodega b inner join b.kardexs k inner join k.producto p where p.ean=?1 order by b.nombre",
						new Object[] { ean });
		return list;
	}

	public List<Bodega> obtenerPorProducto(String codigoId) {
		List<Bodega> list = bodegaDao
				.obtenerPorHql(
						"select b from Bodega b inner join b.productobodegas pb where pb.codigoid=?1",
						new Object[] { codigoId });
		return list;
	}

	public List<Bodega> obtenerTodos() {
		List<Bodega> list = bodegaDao.obtenerPorHql(
				"select distinct b from Bodega b left join fetch b.bodegaempleadocargos "
						+ "left join fetch b.bodegalocals "
						+ "order by b.nombre", new Object[] {});
		return list;
	}
}